import threading
from virtualdevice import virtualdevice
import time
from scapy import *

class router(threading.Thread):
	def __init__(self):
		threading.Thread.__init__(self)
		self.RouteTable = []
		self.VirtualDevices = []
		self.PacketQueue = []
		self.PacketIdCount = 0
		
	def run(self):
		while True:
			# Route Packets
			for PacketToRoute in self.PacketQueue:
				# Determine layer
				PacketId = PacketToRoute["Id"]
				PacketData = PacketToRoute["Data"]
				try:
					if PacketData.getlayer(IP):
						route=self._findroute(PacketData.getlayer(IP).dst)
						if route:
							# Look for device and send packet
							for vdev in self.VirtualDevices:
								if vdev["name"] == route["VDev"]:
									return vdev["dev"].sendpacket(PacketData)
						else:
							print "No route found for:"
							PacketData.summary()
					else:
						# Improve this part!
						pass
				except:
					print "Exception"

				self.PacketQueue.remove(PacketToRoute)
			
			# Read packets from virtualdevices
			for virtualdevice in self.VirtualDevices:
				packet = virtualdevice["dev"].recvpacket()
				if packet:
					self.routepacket(packet)

			time.sleep(0.01)

	def routepacket(self, packet):
		NewPacket = {}
		NewPacket["Id"] = self.PacketIdCount
		if self.PacketIdCount < 65535:
			self.PacketIdCount+=1
		else:
			self.PacketIdCount=0
		NewPacket["Data"] = packet
		self.PacketQueue.append(NewPacket)
		return True

	def addroute(Mac=False, Ip=False, VMac=False, VDev=False, IsNet=False, NetMask=False, VGateway=False, Cost=False):
		route = {}

		if Mac and Ip and VMac and VDev:
			# Check values!
			route["Mac"]     = Mac
			route["Ip"]      = Ip
			route["VMac"]    = VMac
			route["VDev"]    = VDev
			route["IsNet"]   = False

			if not IsNet:
				route["NetMask"] = "255.255.255.255"
			else:
				route["Netmask"] = Netmask

			if not Cost:
				route["Cost"] = 10
			else:
				route["Cost"] = Cost

			self.RouteTable.append(route)
			return True
		else:
			return False
	
	def addvirtualdevice(self, name, parameters):
		try:
			NewDevice = {}
			NewDevice["name"] = name
			NewDevice["dev"]  = virtualdevice(parameters)
			if NewDevice["dev"]:
				NewDevice["dev"].start()
				if NewDevice["dev"].up():
					self.VirtualDevices.append(NewDevice)
				else:
					print "Error with", NewDevice["name"]
			else:
				return False
		except Exception, e:
			print "Except", name, " ", parameters, e
			return False

		return True

	def _findroute(self, dstip):
		for route in self.RouteTable:
			if not route["IsNet"] and route["Ip"] == dstip:
				return route
		# Calc networks

		return False
	

